﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace SDK10kWrapper
{
    partial class Camera
    {
        #region INSTANCE
        /// <summary>
        /// CONNECT TO ONE CAMERA.
        /// </summary>
        /// <param name="cam">The camera that you want to Connect to</param>
        /// <returns>TRUE if connect SUCCESS otherwise FALSE</returns>
        public bool Connect()
        {
            // Create Handle
            try { this.Handle = KOpenInterface(); if (this.Handle == IntPtr.Zero) { MessageBox.Show("KOpenInterface FAIL !", this.Name); return false; } }
            catch (Exception ex) { MessageBox.Show(ex.Message, "KOpenInterface FAIL : " + this.Name); return false; }

            // Test Audio & Set 100% Volume
            try { KSetMute(this.Handle, true); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "KSetMute true FAIL : " + this.Name); return false; }
            try { KSetMute(this.Handle, false); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "KSetMute false FAIL : " + this.Name); return false; }
            try { KSetVolume(this.Handle, 100, 100); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "KSetVolume FAIL"); return false; }

            // Connect to Video Server
            MEDIA_CONNECTION_CONFIG2 mcc = this.MCC2;
            try { bool bMedia = KSetMediaConfig2(this.Handle, ref mcc); if (!bMedia) { MessageBox.Show("KSetMediaConfig2 FAIL!", this.Name); this.Handle = IntPtr.Zero; return false; } }
            catch (Exception ex) { MessageBox.Show(ex.Message, "KSetMediaConfig2 FAIL : " + this.Name); return false; }

            try { bool bConnect = KConnect(this.Handle); if (!bConnect) { MessageBox.Show("KConnect FAIL!", this.Name); this.Handle = IntPtr.Zero; return false; } }
            catch (Exception ex) { MessageBox.Show(ex.Message, "KConnect FAIL : " + this.Name); return false; }

            // Start Streaming
            try { bool bStream = KStartStreaming(this.Handle); if (!bStream) { MessageBox.Show("KStartStreaming FAIL!", this.Name); KDisconnect(this.Handle); this.Handle = IntPtr.Zero; return false; } }
            catch (Exception ex) { MessageBox.Show(ex.Message, "KStartStreaming FAIL : " + this.Name); return false; }

            // Set Media Render Info
            MEDIA_RENDER_INFO mri = this.MRI;
            try { KSetRenderInfo(this.Handle, ref mri); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "KSetRenderInfo FAIL : " + this.Name); return false; }

            return true; // TO HERE mean SUCCESSFULLY
        }

        /// <summary>
        /// DISCONNECT FROM A CAMERA.
        /// </summary>
        /// <param name="cam">The camera that you want to Disconnect from</param>
        /// <returns>TRUE if disconnect SUCCESS otherwise FALSE</returns>
        public bool Disconnect()
        {
            // Check if server connected
            if (this.Handle == IntPtr.Zero) { MessageBox.Show("Disconnect Fail : Connect to SERVER First !", this.Name); return false; }

            // Stop Playing Stream
            try { KStop(this.Handle); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Disconnect Fail at KStop : " + this.Name); return false; }

            // Stop Streaming
            try { KStopStreaming(this.Handle); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Disconnect Fail at KStopStreaming : " + this.Name); return false; }

            // Disconnect Server
            try { KDisconnect(this.Handle); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Disconnect Fail at KDisconnect : " + this.Name); return false; }

            // Close Interface
            try { KCloseInterface(this.Handle); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Disconnect Fail at KCloseInterface : " + this.Name); return false; }

            this.Handle = IntPtr.Zero;
            return true; // TO HERE mean SUCCESSFULLY
        }

        /// <summary>
        /// PLAY PREVIEW ONE CAMERA (need connect to camera already)
        /// </summary>
        /// <param name="cam">The camera that you want to Play Preview</param>
        /// <param name="lowCPU">TRUE will decode I Frame only and help reduce CPU Usage</param>
        /// <returns>TRUE if Play SUCCESS otherwise FALSE</returns>
        public bool Play(bool lowCPU = true)
        {
             // Check if server connected
            if (this.Handle == IntPtr.Zero) { MessageBox.Show("Play Fail : Connect to SERVER First !", this.Name); return false; }

            // Play video streaming
            try { KPlay(this.Handle); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Play Fail at KPlay : " + this.Name); return false; }
            this.IsPlaying = true;

            // Play video streaming
            try { if (lowCPU) KSetDecodeIFrameOnly(this.Handle, true); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Play Fail at KSetDecodeIFrameOnly : " + this.Name); return false; }

            return true; // TO HERE mean SUCCESSFULLY
        }

        /// <summary>
        /// PAUSE PREVIEW ONE CAMERA
        /// </summary>
        /// <param name="cam">The camera that you want to Pause Preview</param>
        /// <returns>TRUE if Pause SUCCESS otherwise FALSE</returns>
        public bool Pause()
        {
            // Check if server connected
            if (this.Handle == IntPtr.Zero) { MessageBox.Show("Pause Fail : Connect to SERVER First !", this.Name); return false; }

            // Pause video Playing
            try { KPause(this.Handle); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Play Fail at KPause : " + this.Name); return false; }
            this.IsPlaying = false;

            return true; // TO HERE mean SUCCESSFULLY
        }

        /// <summary>
        /// STOP PREVIEW ONE CAMERA
        /// </summary>
        /// <param name="cam">The camera that you want to Stop Preview</param>
        /// <returns>TRUE if Stop SUCCESS otherwise FALSE</returns>
        public bool Stop()
        {
            // Check if server connected
            if (this.Handle == IntPtr.Zero) { MessageBox.Show("Stop Fail : Connect to SERVER First !", this.Name); return false; }

            // Stop video Playing
            try { KStop(this.Handle); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Stop Fail at KStop : " + this.Name); return false; }
            this.IsPlaying = false;

            return true; // TO HERE mean SUCCESSFULLY
        }

        /// <summary>
        /// RECORD TO FILE BY A CAMERA (need connect to camera already)
        /// </summary>
        /// <param name="cam">The camera that you want to Record to File</param>
        /// <returns>TRUE if Record SUCCESS otherwise FALSE</returns>
        public bool StartRecord()
        {
            // Check if server connected
            if (this.Handle == IntPtr.Zero) { MessageBox.Show("Start Record Fail : Connect to SERVER First !", this.Name); return false; }

            if (this.IsRecording) { MessageBox.Show("Start Record Fail : Is Recording Already !", this.Name); return false; }

            // Set Pre-record Time and Output File
            /*/try { KSetPrerecordTime(this.Handle, 5); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "KSetPrerecordTime FAIL! : " + this.Name); return false; } /*/

            // Set Writer Type
            try { KSetFileWriterType(this.Handle, (int)FILE_WRITER_TYPES.FAVI); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Start Record Fail at KSetFileWriterType : " + this.Name); return false; }

            // Check if folder exist
            if (!Directory.Exists(this.SavePath)) Directory.CreateDirectory(Path.GetDirectoryName(this.SavePath));

            // Check if file already exist
            //if (File.Exists(this.SavePath)) File.Copy(this.SavePath, this.SavePath + ".bak"

            // Start recording
            try { this.IsRecording = KStartRecord(this.Handle, this.SavePath); if (!this.IsRecording) { MessageBox.Show("Start Record Fail at KStartRecord !", this.Name); return false; } }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Start Record Fail at KStartRecord : " + this.Name); return false; }

            return true; // TO HERE mean SUCCESSFULLY
        }

        /// <summary>
        /// STOP RECORD TO FILE FROM A CAMERA (need start record already)
        /// </summary>
        /// <param name="cam">The camera that you want to Stop Record to File</param>
        /// <returns>Return the File that you just finish Recording. NULL if Stop Record Fail</returns>
        public FileInfo StopRecord()
        {
            if (!this.IsRecording) { MessageBox.Show("Stop Record Fail : No Recording Detected !", this.Name); return null; }

            // Stop recording
            MP4FILE_RECORD_INFO mrec = new MP4FILE_RECORD_INFO(); // Check Code HERE
            try { KStopRecord(this.Handle, ref mrec); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Stop Record Fail at KStopRecord : " + this.Name); return null; }
            this.IsRecording = false; // Be careful DEAD LOCK because Start & Stop Record check for this.IsRecording

            FileInfo fInfo = new FileInfo(this.SavePath);
            if (!fInfo.Exists) return null;
            if (fInfo.Length == 0) return null;

            return fInfo; // TO HERE mean SUCCESSFULLY
        }

        /// <summary>
        /// ON SOUND ONE CAMERA
        /// </summary>
        /// <param name="cam">The camera that you want to On Sound</param>
        /// <returns>TRUE if On SUCCESS otherwise FALSE</returns>
        public bool SoundON()
        {
            // Check if server connected
            if (this.Handle == IntPtr.Zero) { MessageBox.Show("Sound ON Fail : Connect to SERVER First !", this.Name); return false; }

            // Sound ON
            try { KSetMute(this.Handle, false); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Sound ON Fail at KSetMute false : " + this.Name); return false; }

            return true; // TO HERE mean SUCCESSFULLY
        }

        /// <summary>
        /// OFF SOUND ONE CAMERA
        /// </summary>
        /// <param name="cam">The camera that you want to Off Sound</param>
        /// <returns>TRUE if Off SUCCESS otherwise FALSE</returns>
        public bool SoundOFF()
        {
            // Check if server connected
            if (this.Handle == IntPtr.Zero) { MessageBox.Show("Sound OFF Fail : Connect to SERVER First !", this.Name); return false; }

            // Sound OFF
            try { KSetMute(this.Handle, true); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Sound OFF Fail at KSetMute true : " + this.Name); return false; }

            return true; // TO HERE mean SUCCESSFULLY
        }
        #endregion
    }
}
